package Infix2RPM.processor.infixElement;

import Infix2RPM.processor.Exception.BasicOperandException;
import Infix2RPM.processor.Exception.BasicOperatorException;
import Infix2RPM.processor.Exception.LogicException;
import Infix2RPM.processor.Stack.BasicOperand;

public class IntegerOperand implements BasicOperand {
	private Integer value = null;

	public IntegerOperand(Integer value) {
		this.value = value;
	}

	public IntegerOperand add(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to add is not a Integer");
		}
		return new IntegerOperand(this.value + (Integer) operand.getValue());
	}

	public IntegerOperand subtract(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to subtract is not a Integer");
		}
		return new IntegerOperand(this.value.intValue() - ((Integer) operand.getValue()).intValue());
	}

	public IntegerOperand divide(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to divide is not a Integer");
		}
		return new IntegerOperand(this.value.intValue() / ((Integer) operand.getValue()).intValue());
	}

	public IntegerOperand multiply(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to multiply is not a Integer");
		}
		return new IntegerOperand(this.value.intValue() * ((Integer) operand.getValue()).intValue());
	}

	public IntegerOperand power(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to power is not a Integer");
		}
		return new IntegerOperand((int) Math.pow(value, ((Double) operand.getValue()).doubleValue()));
	}

	public IntegerOperand mod(BasicOperand operand) throws BasicOperandException {
		return new IntegerOperand(this.value %= (Integer) operand.getValue());
	}

	public IntegerOperand concat(BasicOperand operand) throws BasicOperandException {
		throw new UnsupportedOperationException("Integer concatentation is unsupported.");
	}
	
	public BooleanOperand equal(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to == is not a Integer");
		}
		return new BooleanOperand(this.value.intValue() == ((Integer) operand.getValue()).intValue());
	}

	public BooleanOperand lessThan(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to < is not a Integer");
		}
		return new BooleanOperand(this.value.intValue() < ((Integer) operand.getValue()).intValue());

	}

	public BooleanOperand lessThanEqual(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to <= is not a Integer");
		}
		return new BooleanOperand(this.value.intValue() <= ((Integer) operand.getValue()).intValue());
	}

	public BooleanOperand greaterThan(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to > is not a Integer");
		}
		return new BooleanOperand(this.value.intValue() > ((Integer) operand.getValue()).intValue());
	}

	public BooleanOperand greaterThanEqual(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to >= is not a Integer");
		}
		return new BooleanOperand(this.value.intValue() >= ((Integer) operand.getValue()).intValue());
	}
	
	public BooleanOperand or(BasicOperand operand) throws LogicException {
		throw new BasicOperatorException(
				"Logical OR using Double is unsupported", this.className());
	}

	public BooleanOperand and(BasicOperand operand) throws LogicException {
		throw new BasicOperatorException(
				"logical AND using Double is unsupported", this.className());
	}


	public boolean isNull() {
		return this.value == null;
	}

	public boolean isEmpty() {
		return this.value == null;
	}

	public Integer getValue() {
		return this.value;
	}

	private void toss(String message) throws BasicOperandException {
		throw new BasicOperandException(message, this.getClass().getName());
	}
	
	public String getValueAsString() {
		return this.value.toString();
	}
	
	public boolean isEqual(String token) {
		return this.value.toString().equals(token);
	}

	private String className() {
		return this.getClass().getName();
	}

}
